package com.googlecode.marrowboy.utilities;

import org.apache.commons.lang.StringEscapeUtils;

/**
 * Various methods to help when dealing with {@link String} objects.
 * 
 * @author mjg
 */
public class StringUtils extends StringEscapeUtils{

	/**
	 * Constructor.
	 */
	public StringUtils() {
	}
	
	/**
	 * General purpose java-thing-to-sentence method.
	 */
	public String toSentence(String classOrMethodName){
	    return camelCaseToSentence(deleteExceptAfterFinalDot(classOrMethodName));
	}

	/**
	 * Turns a fully-qualified class name into the simple name. <br/>
	 * eg: "java.lang.String" -> "String"
	 * 
	 * @param fqName
	 *            the fully-qualified class name.
	 * @return the simple class name.
	 */
	public String deleteExceptAfterFinalDot(final String fqName) {
		return fqName.substring(fqName.lastIndexOf(".") + 1);
	}

	/**
	 * Turns a camelCase String into a String in sentence case, with spaces. <br/>
	 * eg "aMethodName" -> "A method name"<br/>
	 * eg "AClassName" -> "A class name"
	 * 
	 * @param ccString
	 *            a string in camelCase
	 * @return the string in sentence case
	 */
	public String camelCaseToSentence(final String ccString) {

		final StringBuilder out = new StringBuilder();

		boolean firstChar = true;

		final char[] camelCaseCharArray = ccString.toCharArray();

		for (int i = 0; i < camelCaseCharArray.length; i++) {
			final char c = camelCaseCharArray[i];

			if (firstChar) {
				out.append(Character.toUpperCase(c));
				firstChar = false;

			} else if (Character.isUpperCase(c)) {

				if (i == camelCaseCharArray.length - 1) {
					// final character is uppercase
					if (Character.isUpperCase(camelCaseCharArray[i - 1])) {
						out.append(c);
					} else {
						out.append(" ").append(c);
					}

				} else if (Character.isLowerCase(camelCaseCharArray[i + 1])) {
					// we started a new word
					out.append(" ").append(Character.toLowerCase(c));

				} else if (Character.isLowerCase(camelCaseCharArray[i - 1])) {
					// start of an acronym?

					out.append(" ");

					if (i + 2 >= camelCaseCharArray.length || Character.isUpperCase(camelCaseCharArray[i + 2])) {
						// yes, an acronym
						out.append(c);

					} else {
						// no, not an acronym any more
						out.append(Character.toLowerCase(c));

					}

				} else {
					out.append(c);

				}

			} else {
				out.append(c);
			}

		}

		return out.toString();

	}

}
